/*
 * CastDRAndroid
 * Copyright (c) 2014 Christian Holm Christensen
 *
 * This program is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation, either version 3 of the License, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/**
 *
 */
package org.cholm.media.castdr.fragments;

import android.os.Bundle;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.Loader;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ExpandableListView;
import android.widget.TextView;

import org.cholm.media.castdr.Activity;
import org.cholm.media.castdr.LogUtils;
import org.cholm.media.castdr.R;
import org.cholm.media.castdr.adapters.SubCategoryAdapter;
import org.cholm.media.castdr.backend.Category;
import org.cholm.media.castdr.backend.Extractor;
import org.cholm.media.castdr.backend.Program;
import org.cholm.media.castdr.backend.Serie;
import org.cholm.media.castdr.backend.SubCategory;
import org.cholm.media.castdr.loaders.ProgramLoader;
import org.cholm.media.castdr.loaders.SerieLoader;

import java.util.List;

import static org.cholm.media.castdr.LogUtils.LOGd;
import static org.cholm.media.castdr.LogUtils.LOGw;

/**
 * A fragment that show the series (and programs) of a sub-category
 *
 * @author cholm
 */
public class SubCategoryFragment extends android.support.v4.app.Fragment implements
        ExpandableListView.OnChildClickListener,
        ExpandableListView.OnGroupClickListener,
        ExpandableListView.OnGroupCollapseListener,
        ExpandableListView.OnGroupExpandListener {

    /**
     * Debug tag
     */
    private static final String TAG = LogUtils.makeLogTag(SubCategoryFragment.class);
    /**
     * Save category ID
     */
    private IdSaver mCatSaver =
            new IdSaver(TAG
                    + ":Category");
    private IdSaver mSubSaver =
            new IdSaver(TAG
                    + ":SubCategory");
    /**
     * The view
     */
    private View mView = null;
    /**
     * Our list
     */
    private ExpandableListView mList = null;
    /**
     * Our sub-category
     */
    private SubCategory mTarget = null;
    /**
     * Our adapter
     */
    private SubCategoryAdapter mAdapter = null;
    /**
     * If true, then show title
     */
    private boolean mEnableTitle = true;
    /**
     * The current holder - if any
     */
    private SubCategoryAdapter.SerieHolder mCur = null;

    /**
     * Constructor
     */
    public SubCategoryFragment() {
    }

    /**
     * Set the sub-category
     *
     * @param cat Cateogory
     * @param sub Sub-category number
     */
    public void setTarget(int cat, int sub) {
        mCatSaver.setId(cat);
        mSubSaver.setId(sub);
    }

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (savedInstanceState != null) {
            mCatSaver.restore(savedInstanceState);
            mSubSaver.restore(savedInstanceState);
        }
    }

    /**
     * Create our view
     */
    /*
     * (non-Javadoc)
	 *
	 * @see
	 * android.support.v4.app.Fragment#onCreateView(android.view.LayoutInflater,
	 * android.view.ViewGroup, android.os.Bundle)
	 */
    public View onCreateView(LayoutInflater inflator, ViewGroup container,
                             Bundle savedInstance) {
        int catId = mCatSaver.getId();
        int subId = mSubSaver.getId();
        if (catId < 0 || subId < 0) {
            LOGw(TAG, "Ids invalid: " + catId + "/" + subId);
            return null;
        }
        Category cat = Extractor.instance().getList().get(catId);
        if (cat == null) {
            LOGw(TAG, "No category found");
            return null;
        }

        mTarget = cat.getSub(subId);
        if (mTarget == null) {
            LOGw(TAG, "No sub-category found in " + cat.getName());
            return null;
        }

        mView = inflator.inflate(R.layout.serie_list, container, false);
        LOGd(TAG, "Created fragment " + mTarget.getName());

        // Message handler
        mList = (ExpandableListView) mView.findViewById(R.id.listView);
        mAdapter = new SubCategoryAdapter(this.getActivity());
        mList.setEmptyView(mView.findViewById(R.id.progress));
        mList.setOnChildClickListener(this);
        mList.setOnGroupClickListener(this);
        mList.setOnGroupCollapseListener(this);
        mList.setOnGroupExpandListener(this);
        // mList.setChildDivider(null);
        mList.setDividerHeight(0);
        mList.setGroupIndicator(null/* mAdapter.new Indicator() */);
        mList.setChildIndicator(null/* mAdapter.new Indicator() */);

        if (mTarget != null) {
            TextView sub = (TextView) mView.findViewById(R.id.subTitle);
            if (mEnableTitle) {
                sub.setText(mTarget.getName());
            } else sub.setVisibility(View.GONE);

        }

        LOGd(TAG, "Setting adapter for " + mTarget.getName());
        mList.setAdapter(mAdapter);
        load();

        return mView;
    }

    @Override
    public void onDestroyView() {
        LOGd(TAG, "Destroying subFragment: " + mTarget.getName());
        super.onDestroyView();
        mCatSaver.save();
        mSubSaver.save();
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        LOGd(TAG, "Saving instance state " + mCatSaver.getId() + "/"
                + mSubSaver.getId());

        mCatSaver.save(outState);
        mSubSaver.save(outState);
        super.onSaveInstanceState(outState);
    }

    /**
     * When resuming
     */
    public void onResume() {
        super.onResume();
    }

    /**
     * When pausing
     */
    public void onPause() {
        LOGd(TAG, "Pausing fragment " + mTarget.getName());
        Activity a = (Activity) getActivity();
        if (a == null) {
            LOGw(TAG, "No activity!");
            return;
        }
        LOGd(TAG, "Destroying loader");
        LoaderManager lm = a.getSupportLoaderManager();
        lm.destroyLoader(R.integer.serie_loader);
        super.onPause();
    }

    /**
     * Load the sub-category
     */
    public void load() {
        LOGd(TAG, "Now loading the sub-category " + mTarget.getName());
        Activity a = (Activity) getActivity();
        if (a == null) {
            LOGw(TAG, "No activity!");
            return;
        }
        LoaderManager lm = a.getSupportLoaderManager();
        if (lm == null) {
            LOGw(TAG, "No loader mananger");
            return;
        }
        LOGd(TAG, "Initialize the loader");
        lm.restartLoader(R.integer.serie_loader, null, new SerieCallback());
    }

    /**
     * When a group is clicked
     */
    @Override
    public boolean onGroupClick(ExpandableListView parent, View v,
                                int groupPosition, long id) {
        LOGd(TAG, "Clicked group " + groupPosition);
        Serie s = mAdapter.getSerie(groupPosition);
        if (s != null
                && (s.getPrograms() == null || s.getPrograms().size() <= 0)) {
            mCur = (SubCategoryAdapter.SerieHolder) v.getTag();
            if (mCur != null) mCur.mProgress.setVisibility(View.VISIBLE);
            LoaderManager lm = getActivity().getSupportLoaderManager();
            lm.destroyLoader(R.integer.program_loader);
            lm.restartLoader(R.integer.program_loader,
                    null,
                    new ProgramCallback(s));
        }
        return false;
    }

    /**
     * When a child is clicked
     */
    @Override
    public boolean onChildClick(ExpandableListView parent, View v,
                                int groupPosition, int childPosition, long id) {
        Program p = mAdapter.getProgram(groupPosition, childPosition);
        if (p == null) {
            LOGw(TAG, "No program at given posistion");
            return true;
        }

        Activity a = (Activity) getActivity();
        a.playProgram(p);
        return true;
    }

    // --- Event listeners ------------------------------------------

    /**
     * When a group is expanded
     */
    @Override
    public void onGroupExpand(int groupPosition) {
        LOGd(TAG, "Expanded " + groupPosition);
        for (int i = 0; i < mAdapter.getGroupCount(); i++) {
            if (i == groupPosition) continue;
            mList.collapseGroup(i);
        }
    }

    /**
     * When a group is collapsed
     */
    @Override
    public void onGroupCollapse(int groupPosition) {
        LOGd(TAG, "Collapsing " + groupPosition);
    }

    public void setEnableTitle(boolean enable) {
        mEnableTitle = enable;
    }

    /**
     * Call-backs on serie loader
     *
     * @author cholm
     */
    private class SerieCallback implements
            LoaderManager.LoaderCallbacks<List<Serie>> {
        /**
         * Debug TAG
         */
        private final String TAG = LogUtils.makeLogTag("SubCategoryFragment" +
                ".SerieCallback");

        // --- Loader ---------------------------------------------------

        /**
         * Create a loader
         */
        @Override
        public Loader<List<Serie>> onCreateLoader(int arg0, Bundle arg1) {
            LOGd(TAG, "Creating loader");
            return new SerieLoader(getActivity(), mTarget);
        }

        /**
         * When the loader finished
         */
        @Override
        public void onLoadFinished(Loader<List<Serie>> ldr, List<Serie> data) {
            LOGd(TAG, "Loader finished");
            // Set data on adapter
            mAdapter.setData(data);
            // Let it know that the content changed
            if (data != null && data.size() > 0)
                mAdapter.notifyDataSetChanged();
            else {
                LOGd(TAG, "Got no data");
                mAdapter.notifyDataSetInvalidated();
                View v = mView.findViewById(R.id.progress);
                if (v != null) v.setVisibility(View.INVISIBLE);
            }
            // Remove the empty view of the list
            mList.setEmptyView(mView.findViewById(R.id.emptyText));
            ldr.stopLoading();
        }

        /**
         * When loader is reset
         */
        @Override
        public void onLoaderReset(Loader<List<Serie>> arg0) {
            LOGd(TAG, "Reset loader");

        }
    }

    /**
     * Call-backs for the programs of a serie
     *
     * @author cholm
     */
    private class ProgramCallback implements
            LoaderManager.LoaderCallbacks<List<Program>> {
        /**
         * Debug tag
         */
        private final String TAG = LogUtils.makeLogTag("SubCategoryFragment" +
                ".ProgramCallback");
        /**
         * Serie
         */
        public Serie mSerie = null;

        /**
         * Constructor
         *
         * @param s Serie object
         */
        ProgramCallback(Serie s) {
            mSerie = s;
        }

        // --- Loader ---------------------------------------------------

        /**
         * Create a loader
         */
        @Override
        public Loader<List<Program>> onCreateLoader(int arg0, Bundle arg1) {
            LOGd(TAG, "Creating loader");
            return new ProgramLoader(getActivity(), mSerie);
        }

        /**
         * When the loader finished
         */
        @Override
        public void onLoadFinished(Loader<List<Program>> ldr, List<Program> data) {
            LOGd(TAG, "Loader finished");
            // Remove the progress
            if (mCur != null) {
                mCur.mProgress.setVisibility(View.INVISIBLE);
                mCur = null;
            }
            mAdapter.notifyDataSetChanged();
            ldr.stopLoading();
        }

        /**
         * When loader is reset
         */
        @Override
        public void onLoaderReset(Loader<List<Program>> arg0) {
            LOGd(TAG, "Reset loader");

        }
    }
}
// EOF
